package com.leedsoft.config.spring_config;

import com.leedsoft.generated.UsersMapper;
import com.leedsoft.spittr.BookFacadeCondition;
import com.leedsoft.spittr.aop.proxy_test.cglib.BookFacadeImpl2;
import com.leedsoft.spittr.aop.proxy_test.jdk.BookFacadeImpl;
import com.leedsoft.spittr.qualifers.Book1;
import com.leedsoft.spittr.qualifers.Book2;
import com.mysql.jdbc.Driver;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.aspectj.lang.annotation.Before;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.bind.annotation.ControllerAdvice;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * spring root容器相关配置
 */
@Configuration
@ComponentScan(basePackages = {"com.leedsoft.spittr", "com.leedsoft.generated"},
        excludeFilters = @Filter({Controller.class, ControllerAdvice.class}))
@EnableTransactionManagement//启动@Transactional注解驱动事务的支持
@PropertySource(value = {"classpath:main.properties", "classpath:common.properties"})
@PropertySource(value = {"classpath:main.properties", "classpath:common.properties"}, encoding = "utf-8")
@EnableAspectJAutoProxy//启用自动代理功能
public class RootConfig {
    // TODO: 2017/11/15 JNDI方式，暂时搁置
//    /**
//     * 数据源 DataSource
//     * 1、配置JNDI， 从web服务器获取DataSource
//     * 2、连接池配置也在JNDI中
//     */
//    @Bean
//    public DataSource jndiDatasource() {
//        //而JndiObjectFactoryBean继承的是FactoryBean<Object>，所以IDE无法识别实际生成的bean的类型
//        JndiObjectFactoryBean jndi = new JndiObjectFactoryBean();
//        jndi.setJndiName("jndi/mybatis");
//        jndi.setResourceRef(true);
//        jndi.setProxyInterface(DataSource.class);
//        DataSource ds = (DataSource) jndi.getObject();
//        return ds;
//    }


    @Autowired
    Environment env;

    @Profile("prod")
    @Bean
    public DataSource dataSource() {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(env.getProperty("jdbc.driver"));
        ds.setUrl(env.getProperty("jdbc.url"));
        ds.setUsername(env.getProperty("jdbc.username"));
        ds.setPassword(env.getProperty("jdbc.password"));

        ds.setInitialSize(5);
        ds.setMaxTotal(100);
        ds.setMaxIdle(30);
        ds.setMaxWaitMillis(30000);
        return ds;
    }
    // TODO: 2017/11/15 嵌入式数据库脚本语法暂时未知。应使用【标准sql】，提高数据可移植性
    @Profile("dev")
    @Bean
    public DataSource embeddedDataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.DERBY)
                .setScriptEncoding("utf-8")
                .addScript("classpath:test_spring.sql")
                .build();
    }

    @Conditional(BookFacadeCondition.class)
    @Bean
    public BookFacadeImpl bookFacade() {
        return new BookFacadeImpl();
    }

//    @Primary
    @Bean
    @Book1
    public BookFacadeImpl2 bookFacadeImpl2() {
        BookFacadeImpl2 impl2 = new BookFacadeImpl2();
        impl2.setName("primary");
        return impl2;
    }

    @Bean
    @Book2
    public BookFacadeImpl2 bookFacadeImpl22() {
        BookFacadeImpl2 impl2 = new BookFacadeImpl2();
        impl2.setName("second");
        return impl2;
    }



    /**
     * 事务管理器 TransactionManager
     */
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }

    //-------------------------------------mybatis begin---------------------------------------
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource, ResourcePatternResolver resolver) throws IOException {
        //SqlSessionFactoryBean继承了FactoryBean<SqlSessionFactoryBean>。。所以IDE可以识别出实际生成的是SqlSessionFacory
        SqlSessionFactoryBean s = new SqlSessionFactoryBean();
        s.setDataSource(dataSource);
        //查看javaDoc，可以使用Resource Pattern
        s.setMapperLocations(resolver.getResources("classpath:mappers/**/*.xml"));
        s.setTypeAliasesPackage(
                String.join(",", UsersMapper.class.getPackage().getName()));
        return s;
    }

    @Bean
    public static MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage(UsersMapper.class.getPackage().getName());
        return configurer;
    }
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        return template;
    }
    //-------------------------------------mybatis end---------------------------------------


    public static void main(String[] args) {
        System.out.println(Driver.class.getName());
    }
}
